import { defineStore } from "pinia"
import { type Menu } from "@/api/menu/types/menu"
import store from "@/store"
import { menuAllApi } from "@/api/menu"
import { constantRoutes } from "@/router"
import type { RouteRecordRaw } from "vue-router"
import router from "@/router"
import { useUserStoreHook } from "./user"

const modules = import.meta.glob(["@/views/**/*.vue"], { eager: true })
const layout = import("@/layouts/index.vue")

const hasPermission = (roles: string[], route: RouteRecordRaw) => {
  const routeRoles = route.meta?.roles
  /** 角色是空，代表没有权限限制 */
  if (routeRoles && routeRoles?.length === 0) return true
  return routeRoles ? roles.some((role) => routeRoles.includes(role)) : true
}

const filterDynamicRoutes = (routes: RouteRecordRaw[], roles: string[]) => {
  const res: RouteRecordRaw[] = []
  routes.forEach((route) => {
    const tempRoute = { ...route }
    if (hasPermission(roles, tempRoute) && tempRoute.meta?.type !== "permission") {
      if (tempRoute.children) {
        tempRoute.children = filterDynamicRoutes(tempRoute.children, roles)
      }
      res.push(tempRoute)
    }
  })
  return res
}

/** 把Menu的数据copy到RouteRecordRaw中 */
const copy = (menu: Menu) => {
  const route = {} as RouteRecordRaw
  route.path = menu.path
  route.redirect = menu.redirect
  route.meta = {
    ...menu.meta,
    type: menu.menuType,
    routeDel: menu.del
  }
  if (menu.component === "layout") {
    route.component = () => layout
  } else {
    const component = modules["/src/views" + menu.component]
    if (component) {
      route.component = async () => component
    } else {
      route.component = async () => await modules["/src/views/error-page/404.vue"]
    }
  }
  route.name = menu.name
  return route
}

const toRouteRecordRaw = (menus: Menu[]): RouteRecordRaw[] => {
  if (menus === null || menus === undefined) return []
  const routes: RouteRecordRaw[] = []
  menus.forEach((menu) => {
    let child = [] as RouteRecordRaw[]
    if (menu.child !== undefined) {
      child = toRouteRecordRaw(menu.child)
    }
    const route = copy(menu)
    if (child.length > 0) {
      route.children = child
    }
    routes.push(route)
  })
  return routes
}

export const useMenuStore = defineStore("menu", {
  state: () => {
    return {
      /** 动态路由 */
      dynamicRoute: [] as RouteRecordRaw[],
      /** 固定路由 */
      fixedRoute: constantRoutes,
      /** 后端请求回来的菜单，会转换为dynamicMenu */
      /** 至于为什么不直接使用RouteRecordRaw，因为使用自己定义的Menu可以兼容RouteRecordRaw，也可以自己定义一些特殊的业务 */
      menus: [] as Menu[] | null,
      /** 动态路由 + 固定路由 */
      allRoute: [] as RouteRecordRaw[],
      operation: {
        menu: {} as Menu
      },
      /** 标识一下请求状态 */
      code: 200
    }
  },
  actions: {
    async allMenu() {
      const { body, code } = await menuAllApi()
      this.menus = body
      this.code = code
      if (body !== null && body !== undefined) {
        const userStore = useUserStoreHook()
        this.dynamicRoute = filterDynamicRoutes(toRouteRecordRaw(body), userStore.roles)
      }
      this.allRoute = [...this.fixedRoute, ...this.dynamicRoute]
      this.dynamicRoute.forEach((dr: RouteRecordRaw) => router.addRoute(dr))
    },
    currendMenuOp(menu: Menu) {
      this.operation.menu = menu
    }
  },
  getters: {
    getMenu: (state): Menu[] => {
      if (state.menus === null) return []
      return state.menus
    },
    currendMenu: (state): Menu => {
      return state.operation.menu
    }
  }
})

/** 在组合API中使用 */
export function useMenuStoreHook() {
  return useMenuStore(store)
}
